package com.xb.loan.usercenter.user.user.service.impl;

import com.xb.loan.account.service.ICashService;
import com.xb.loan.account.service.ICashStatService;
import com.xb.loan.account.service.ILotCashService;
import com.xb.loan.account.service.IPointService;
import com.xb.loan.account.service.bean.CashInfoVO;
import com.xb.loan.account.service.bean.CashStatVO;
import com.xb.loan.account.service.bean.LotCashInfoVO;
import com.xb.loan.account.service.bean.PointInfoVO;
import com.xb.loan.account.service.constant.AccountConst;
import com.xb.loan.log.exception.BizException;
import com.xb.loan.usercenter.service.user.IUserService;
import com.xb.loan.usercenter.service.user.bean.*;
import com.xb.loan.usercenter.service.user.constant.UserConst;
import com.xb.loan.usercenter.service.user.exception.IUserServiceException;
import com.xb.loan.usercenter.user.user.dao.UserInfoDao;
import com.xb.loan.usercenter.user.user.dao.UserPhoneValDao;
import com.xb.loan.usercenter.user.user.dao.bean.UserInfo;
import com.xb.loan.usercenter.user.user.dao.bean.UserInfoIdentify;
import com.xb.loan.usercenter.user.user.dao.bean.UserInfoIdentifyBank;
import com.xb.loan.usercenter.user.util.PropertyConf;
import com.xb.loan.util.cache.redis.comm.FormatOperation;
import com.xb.loan.util.common.ObjectOperation;
import com.xb.loan.util.log.DefaultLoggerFacotry;
import com.xb.loan.util.mybatis.MyTransactional;
import com.xb.loan.usercenter.service.user.bean.*;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * 类  描  述 : 用户信息处理业务类
 */
@Service("userService")
public class UserServiceImpl implements IUserService,IUserServiceException {

    private static final Logger logger = DefaultLoggerFacotry.getLogger(UserServiceImpl.class);

    @Autowired
    private UserInfoDao userInfoDao;
    
    @Autowired
    private UserPhoneValDao userPhoneValDao;

    @Autowired(required = true)
    private ICashService cashService;
    
    @Autowired(required = true)
    private IPointService pointService;
    
    @Autowired(required = true)
    private ILotCashService lotCashService;
    
    @Autowired(required = true)
    private ICashStatService cashStatService;
    
    @Autowired  //①  注入上下文  
    private PropertyConf propertyConf;

    @Autowired  //①  注入上下文  
    private ApplicationContext context;  
    
    private UserServiceImpl proxySelf; //②  表示代理对象，不是目标对象
    
    @PostConstruct  //③ 初始化方法
    private void setSelf() {
        //从上下文获取代理对象（如果通过proxtSelf=this是不对的，this是目标对象）  
        //此种方法不适合于prototype Bean，因为每次getBean返回一个新的Bean  
        proxySelf = (UserServiceImpl) context.getBean(IUserService.class);   
    }

	public UserInfoVO queryUserInfoByToken(String token) throws BizException {
		UserInfo userInfo = userInfoDao.queryUserInfoByToken(token);
		if (userInfo != null && userInfo.getToken() != null && userInfo.getUserId() != null){
			return ObjectOperation.convertByClasses(userInfo, UserInfoVO.class);
		}else{
			return null;
		}
	}

	/**
     * 生成渠道用户信息，信息（登录名、密码）应由外部组装完成
     */
    public String generateUser(UserInfoVO userInfoVO, int partnerLevel) throws BizException {
    	String userId = generateUserIdBySeq();
    	userInfoVO.setUserId(userId);
    	userInfoVO.setUserLevel(UserConst.UserLevel.CHANNEL.getCode());
    	userInfoVO.setStatus(UserConst.UserStatus.NORMALSTATUS.getCode());
    	userInfoVO.setAccountId(userId);
    	userInfoVO.setCreateTime(FormatOperation.formatDateToYMDHms14(new Date()));
    	
        UserInfo userInfo = ObjectOperation.convertByClasses(userInfoVO, UserInfo.class);
    	
    	proxySelf.addUserTransaction(userInfo);
    	return userId;
    }
    
    //--------------------------------实名注册开始------------------------------------------------------------------------
    @Override
    public LoginInfoVO registerUser(int userType, String partnerId, String loginName, String pwd) throws BizException {
    	UserInfo userInfo = new UserInfo();
    	/*userInfo.setUserId(FormatOperation.assemblySeq(UserConst.UserSeq.COMMONUSER.getName(),
				UserConst.UserSeq.COMMONUSER.getCode()));*/
    	userInfo.setUserLevel(UserConst.UserLevel.NORMAL.getCode());
    	userInfo.setUserType(userType);
    	userInfo.setPhone(loginName);//O2O业务，手机号为登录名
    	userInfo.setLoginName(loginName);
    	userInfo.setPwd(pwd);
    	userInfo.setStatus(UserConst.UserStatus.NORMALSTATUS.getCode());
    	userInfo.setAccountId(userInfo.getUserId()+"");
    	userInfo.setCreateTime(FormatOperation.formatDateToYMDHms14(new Date()));
    	
    	proxySelf.addUserTransaction(userInfo);
    	
    	LoginInfoVO loginInfoVO = new LoginInfoVO();
    	loginInfoVO.setUserId(userInfo.getUserId());
    	loginInfoVO.setStatus(userInfo.getStatus());
    	loginInfoVO.setPwd(pwd);
    	loginInfoVO.setLoginName(loginName);
    	Date curDate = new Date();
    	loginInfoVO.setLastAccessTime(curDate);
    	loginInfoVO.setLastLoginTime(curDate);
    	/*if(propertyConf.getExpiredTime() != null){
    		loginInfoVO.setExpiredTime(propertyConf.getExpiredTime());
    	}*/
        return loginInfoVO;
    }

    //--------------------------------即开实名注册开始------------------------------------------------------------------------
    @Override
    public WinstantLoginInfoVO registerWinstantUser(int userType, String partnerId, String loginName, String pwd) throws BizException {
    	UserInfo userInfo = new UserInfo();
    	userInfo.setUserId(FormatOperation.assemblySeq(UserConst.UserSeq.COMMONUSER.getName(), UserConst.UserSeq.COMMONUSER.getCode()));
    	userInfo.setUserLevel(UserConst.UserLevel.NORMAL.getCode());
    	userInfo.setUserType(userType);
    	userInfo.setPhone(loginName);//即开票业务，手机号为登录名
    	userInfo.setLoginName(userInfo.getUserId());//即开票业务，登录名默认设置为userId
    	userInfo.setPwd(pwd);
    	userInfo.setStatus(UserConst.UserStatus.NORMALSTATUS.getCode());
    	userInfo.setAccountId(userInfo.getUserId());
    	userInfo.setCreateTime(FormatOperation.formatDateToYMDHms14(new Date()));
    	
    	proxySelf.addUserTransaction(userInfo);
    	
    	WinstantLoginInfoVO loginInfoVO = new WinstantLoginInfoVO();
    	loginInfoVO.setUserId(userInfo.getUserId());
    	loginInfoVO.setStatus(userInfo.getStatus());
    	loginInfoVO.setPwd(pwd);
    	loginInfoVO.setLoginName(loginName);
    	Date curDate = new Date();
    	loginInfoVO.setLastAccessTime(curDate);
    	loginInfoVO.setLastLoginTime(curDate);
    	loginInfoVO.setRealFlag(UserConst.UserRealFlag.NOREAL.getCode());
    	/*if(propertyConf.getExpiredTime() != null){
    		loginInfoVO.setExpiredTime(propertyConf.getExpiredTime());
    	}*/
        return loginInfoVO;
    }
    
    /**
     * 
     * 用户注册，保存数据
     * @param userInfo         用户实例
     * 2015年11月11日 by wuqinglong
     * @throws BizException 
     */
    @MyTransactional
    public void addUserTransaction(UserInfo userInfo) throws BizException {
    	/** 创建帐户信息 */
        CashInfoVO cashInfo = createCashInfo(userInfo.getUserId());
        /**创建帐户累积信息*/
        CashStatVO cashStat = createCashStat(userInfo.getUserId());
        /** 创建彩金帐户、创建积分帐户*/
        LotCashInfoVO lotCashInfo = createLotCashInfo(userInfo.getUserId());
        PointInfoVO pointInfo = createPointInfo(userInfo.getUserId());
        
        cashService.createCashInfo(cashInfo);
        userInfoDao.insert(userInfo);
        lotCashService.createLotCash(lotCashInfo);
        pointService.createPointInfo(pointInfo);
        cashStatService.createCashStat(cashStat);
    }

    /**
     * 根据序列生成userId
     * 渠道用户: 大小不能超过10个字节
     * 普通用户: 年月日时分秒 + 6位随机数字
     * @return     返回用户编码
     * 2015年9月1日 by wuqinglong
	 *
     */
    private String generateUserIdBySeq() {
    	String userSeq = FormatOperation.assemblySeq(UserConst.UserSeq.COMMONUSER.getName(),
				UserConst.UserSeq.COMMONUSER.getCode(),
				FormatOperation.formatDateToYMDHms(new Date()), null);
        return userSeq;
    }
    
    /**
     * 生成账户基本信息
     */
    private CashInfoVO createCashInfo(String userId){
        CashInfoVO cashInfo = new CashInfoVO();
        cashInfo.setAccountId(userId);
        cashInfo.setStatus(AccountConst.AccountStatus_Normal);
        return cashInfo;
    }
    
    /**
     * 生成账户累积信息
     */
    private CashStatVO createCashStat(String accountId){
        CashStatVO cashStat = new CashStatVO();        
        cashStat.setAccountId(accountId);
        return cashStat;
    }
    
    /**
     * 创建彩金帐户
     */
    private LotCashInfoVO createLotCashInfo(String userId){
        LotCashInfoVO lotCashInfo = new LotCashInfoVO();
        lotCashInfo.setAccountId(userId);
        lotCashInfo.setStatus(AccountConst.AccountStatus_Normal);        
        return lotCashInfo;
    }
    
    /**
     * 创建积分帐户
     */
    private PointInfoVO createPointInfo(String userId){
        PointInfoVO pointInfo = new PointInfoVO();
        pointInfo.setAccountId(userId);
        pointInfo.setStatus(AccountConst.AccountStatus_Normal);
        return pointInfo;
    }

	public int updatePhone(String userId, String phone) throws BizException{
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("userId", userId);
		params.put("phone", phone);
		return userInfoDao.updateUserInfo(params);
	}

	public int updateRealId(String userId, String realId) throws BizException{
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("userId", userId);
		params.put("realId", realId);
		return userInfoDao.updateUserInfo(params);
	}
	
	public int updateLoginName(String userId, String loginName) throws BizException{
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("userId", userId);
		params.put("loginName", loginName);
		return userInfoDao.updateUserInfo(params);
	}

	public int updatePwd(String userId, String pwd) throws BizException{
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("userId", userId);
		params.put("pwd", pwd);
		return userInfoDao.updateUserInfo(params);
	}

	public int updatePayPwd(String userId, String payPwd) throws BizException{
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("userId", userId);
		params.put("payPwd", payPwd);
		return userInfoDao.updateUserInfo(params);
	}

    public void freezeUser(String userId) throws BizException {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("userId", userId);
        map.put("status", UserConst.UserStatus.FROZENSTATUS.getCode());
        userInfoDao.updateUserInfo(map);
    }

    public void unFreezeUser(String userId) throws BizException {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("userId", userId);
        map.put("status", UserConst.UserStatus.NORMALSTATUS.getCode());

        userInfoDao.updateUserInfo(map);
    }

    public int updateUserState(String userId, Integer state) throws BizException {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("userId", userId);
        map.put("status", state);
        return userInfoDao.updateUserInfo(map);
    }

	@Override
	public int updateLastLoginTime(String userId, Date lastLoginTime,String token,Date effDate)
			throws BizException {
		Map<String, Object> map = new HashMap<String, Object>();
        map.put("userId", userId);
        map.put("lastLoginTime", lastLoginTime);
        map.put("token",token);
        map.put("effDate",effDate);
        return userInfoDao.updateUserInfo(map);
	}

    @Override
    public UserInfoVO queryUserInfoById(String userId) throws BizException {
        UserInfo userInfo = userInfoDao.queryUserInfoById(userId);
        return ObjectOperation.convertByClasses(userInfo, UserInfoVO.class);
    }
    
    @Override
    public UserInfoVO queryAnyUserInfoById(String userId) throws BizException {
        UserInfo userInfo = userInfoDao.queryAnyUserInfoById(userId);
        return ObjectOperation.convertByClasses(userInfo, UserInfoVO.class);
    }

    @Override
    public List<UserInfoVO> queryUserInfoByRealId(Integer userType, String realId) throws BizException {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("realId", realId);
		params.put("userType", userType);
    	List<UserInfo> uiList = userInfoDao.queryUserInfoByRealId(params);
        return ObjectOperation.convertByClassesList(uiList, UserInfoVO.class);
    }
    
    public UserInfoVO queryUserInfoByUserType(int userType,String loginName) throws BizException{
    	Map<String, Object> params = new HashMap<String, Object>();
    	params.put("userType", userType);
    	params.put("loginName", loginName);
    	UserInfo userInfo = userInfoDao.queryUserInfoByUserType(params);
    	return ObjectOperation.convertByClasses(userInfo, UserInfoVO.class);
    }
    
    public UserInfoVO queryUserInfoByPhone(int userType,String phone) throws BizException{
    	Map<String, Object> params = new HashMap<String, Object>();
    	params.put("userType", userType);
    	params.put("phone", phone);
    	UserInfo userInfo = userInfoDao.queryUserInfoByUserType(params);
    	return ObjectOperation.convertByClasses(userInfo, UserInfoVO.class);
    }
    
    public List<UserInfoVO> queryUserInfo(String loginName, String partnerId, String phone, String startTime,
                                          String endTime, int pageNum, int numPerPage) throws BizException {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("loginName", loginName);
        map.put("partnerId", partnerId);
        map.put("phone", phone);
        map.put("startTime", startTime);
        map.put("endTime", endTime);
        map.put("pageNum", pageNum);
        map.put("numPerPage", numPerPage);

        List<UserInfo> list = userInfoDao.queryUserInfo(map);
        if (list == null || list.size() <= 0) {
            return null;
        }

        return ObjectOperation.convertByClassesList(list, UserInfoVO.class);
    }
    
    public int queryUserInfoCount(String loginName, String partnerId, String phone,
                                  String startTime, String endTime) throws BizException {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("loginName", loginName);
        map.put("partnerId", partnerId);
        map.put("phone", phone);
        map.put("startTime", startTime);
        map.put("endTime", endTime);

        return userInfoDao.queryUserInfoCount(map);
    }

	public List<Map<String, Object>> queryUserDetailAccess(String userId, String userLevel, String userName, String loginName,
                                                           String cardNum, String phoneNum, String partnerLevel,
                                                           String startTime, String endTime, int pageNum, int numPerPage) {
		
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("userLevel", userLevel);
		map.put("userId", userId);
		map.put("userName", userName);
		map.put("cardNum", cardNum);
		map.put("phoneNum", phoneNum);
		map.put("partnerLevel", partnerLevel);
		map.put("startTime", startTime);
		map.put("endTime", endTime);
		map.put("pageNum", pageNum);
		map.put("numPerPage", numPerPage);
		map.put("loginName", loginName);
		List<Map<String, Object>> list = userInfoDao.queryUserDetailAccess(map);
		
		for (Map<String, Object> map2 : list) {
			int status = 0;
			if(map2.get("STATUS") != null){
				status = Integer.parseInt((String)map2.get("STATUS"));
			}
			if(UserConst.UserStatus.NORMALSTATUS.getCode() == status){
				map2.put("STATUSSTR", UserConst.UserStatus.NORMALSTATUS.getMsg());
			}else if(UserConst.UserStatus.FROZENSTATUS.getCode() == status){
				map2.put("STATUSSTR", UserConst.UserStatus.FROZENSTATUS.getMsg());
			}else if(UserConst.UserStatus.LOGOFFSTATUS.getCode() == status){
				map2.put("STATUSSTR", UserConst.UserStatus.LOGOFFSTATUS.getMsg());
			}else if(UserConst.UserStatus.UNBINDAPPLYSTATUS.getCode() == status){
				map2.put("STATUSSTR", UserConst.UserStatus.UNBINDAPPLYSTATUS.getMsg());
			}else if(UserConst.UserStatus.UNBINDAPPLYSUCCESSSTATUS.getCode() == status){
				map2.put("STATUSSTR", UserConst.UserStatus.UNBINDAPPLYSUCCESSSTATUS.getMsg());
			}else{
				map2.put("STATUSSTR", "状态不确定");
			}
		}
		return list;
	}

	public int queryUserDetailCountAccess(String userId, String userLevel, String userName, String loginName, String cardNum,
                                          String phoneNum, String partnerLevel, String startTime,
                                          String endTime) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("userLevel", userLevel);
		map.put("userId", userId);
		map.put("userName", userName);
		map.put("cardNum", cardNum);
		map.put("phoneNum", phoneNum);
		map.put("partnerLevel", partnerLevel);
		map.put("startTime", startTime);
		map.put("endTime", endTime);
		map.put("loginName", loginName);
		
		int intNum = userInfoDao.queryUserDetailCountAccess(map);
		
		return intNum;
	}

	@Override
	public RegisterUserVO statRegisterUser(String partnerId) {

		RegisterUserVO registerUserVO = new RegisterUserVO();
		int totalUserCount = userInfoDao.queryTotalRegisterUserCount(partnerId);
		int todayUserCount = userInfoDao.queryTodayRegisterUserCount(partnerId);
		registerUserVO.setTotalUserCount(totalUserCount);
		registerUserVO.setTodayUserCount(todayUserCount);
		return registerUserVO;
	}

	@Override
	public int updatePhoneLoginName(String userId, String phone) throws BizException {
		
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("userId", userId);
		map.put("phone", phone);
		map.put("loginName", phone);
		return userInfoDao.updateUserInfo(map);
	}

	@Override
	public int updateUserInfoObj(UserInfoVO userInfoVO) {
		
		UserInfo userInfo=ObjectOperation.convertByClasses(userInfoVO, UserInfo.class);
		return userInfoDao.updateUserInfoObj(userInfo);
	}


	@Override
	public int updateRealIdNickName(String userId, String nickName,
                                    String realId) throws BizException {

		Map<String, Object> params = new HashMap<String, Object>();
		params.put("userId", userId);
		params.put("realId", realId);
		params.put("nickName", nickName);
		return userInfoDao.updateUserInfo(params);
	}

	@Override
	public int logoff(String userId) throws BizException {
		
        if (userId == null || userId.length() == 0) {
            throw userIdMissing;
        }
        
        UserInfo userInfo=userInfoDao.queryUserInfoById(userId);
        if(userInfo==null){
            logger.warn(userInfoMissing.getMessage(), userInfoMissing);
            throw userInfoMissing;
        }
        Map<String, Object> params = new HashMap<String, Object>();
		params.put("userId", userId);
		params.put("status", UserConst.UserStatus.LOGOFFSTATUS.getCode());
        return userInfoDao.updateUserInfo(params);
	}

	@Override
	public List<UserInfoIdentifyBankVO> queryUserInfoIdentifyBank(Integer userType,
																  String startTime, String endTime, int pageNum, int numPerPage) {
		
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("userType", userType);
		map.put("startTime", startTime);
		map.put("endTime", endTime);
		map.put("pageNum", pageNum);
		map.put("numPerPage", numPerPage);
		List<UserInfoIdentifyBank> userList = userInfoDao.queryUserInfoIdentifyBank(map);
		if(userList != null && userList.size()>0){
			return ObjectOperation.convertByClassesList(userList, UserInfoIdentifyBankVO.class);
		}
		return null;
	}
	
	@Override
	public int queryUserInfoIdentifyBankCount(Integer userType, String startTime, String endTime) {
		
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("userType", userType);
		map.put("startTime", startTime);
		map.put("endTime", endTime);
		return userInfoDao.queryUserInfoIdentifyBankCount(map);
	}

	@Override
	public List<UserInfoIdentifyVO> queryUserInfoIdentify(Integer userType,
                                                          String startTime, String endTime, int pageNum, int numPerPage) {
		
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("userType", userType);
		map.put("startTime", startTime);
		map.put("endTime", endTime);
		map.put("pageNum", pageNum);
		map.put("numPerPage", numPerPage);
		List<UserInfoIdentify> userList = userInfoDao.queryUserInfoIdentify(map);
		if(userList != null && userList.size()>0){
			return ObjectOperation.convertByClassesList(userList, UserInfoIdentifyVO.class);
		}
		return null;
	}

	@Override
	public int queryUserInfoIdentifyCount(Integer userType, String startTime,
                                          String endTime) {
		
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("userType", userType);
		map.put("startTime", startTime);
		map.put("endTime", endTime);
		return userInfoDao.queryUserInfoIdentifyCount(map);
	}

}
